﻿using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;

namespace DotNetCommon.Extensions
{
    /// <summary>
    /// MethodInfo 的扩展类
    /// </summary>
    public static class MethodInfoExtensions
    {
        private static ConcurrentDictionary<MethodInfo, string> methodNamesCache = new ConcurrentDictionary<MethodInfo, string>();
        /// <summary>
        /// 获取方法的详细描述，返回格式: "[static ]返回值 类.方法名&lt;泛型列表&gt;(参数列表)"，不考虑其他修饰符
        /// </summary>
        /// <param name="methodInfo"></param>
        /// <returns></returns>
        public static string GetMethodFullName(this MethodInfo methodInfo)
        {
            if (methodInfo == null) return null;
            return methodNamesCache.GetOrAdd(methodInfo, methodInfo =>
            {
                var className = methodInfo.DeclaringType.GetClassFullName();
                var methodName = methodInfo.Name;
                var returnName = methodInfo.ReturnType.GetClassFullName().ToString();
                var genes = "";
                var staticName = methodInfo.IsStatic ? "static " : "";

                if (methodInfo.IsGenericMethod)
                {
                    //泛型方法
                    var types = methodInfo.GetGenericArguments();
                    genes = types.Select(i => i.GetClassFullName()).ToStringSeparated(",");
                    genes = $"<{genes}>";
                }

                var arguments = methodInfo.GetParameters();
                var arr = new string[arguments.Length];
                for (int i = 0; i < arguments.Length; i++)
                {
                    var parameter = arguments[i];
                    var parameterTypeName = parameter.ParameterType.GetClassFullName();
                    var parameterName = parameter.Name;
                    arr[i] = $"{parameterTypeName} {parameterName}";
                }
                return $"{staticName}{returnName} {className}{genes}.{methodName}({arr.ToStringSeparated(", ")})";
            });
        }
    }
}
